﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.IService;
using Pay.Service.Cache;
using Pay.TO;

namespace Pay.Service {
    public class SkuInfoService : ServiceBase, ISkuInfoService, IDisposable {
        private IUnitOfWork _iUnitOfWork;
        private IMerchantService _iMerchantService;

        public SkuInfoService(IUnitOfWork iUnitOfWork, IMerchantService iMerchantService) : base(iUnitOfWork) {
            _iUnitOfWork = iUnitOfWork;
            _iMerchantService = iMerchantService;
        }

        public IEnumerable<sku_info_dto> Gets(long merchant_id) {
            Expression<Func<SkuInfo, bool>> filter = c => true;
            if (merchant_id > 0)
                filter = filter.And(c => c.MerchantId == merchant_id);
            return context.SkuInfos.Where(filter).FromCache<SkuInfo, sku_info_dto>();
        }

        public PagedResult<sku_info_dto> Gets(SPC_SkuQuery query) {
            var filter = PredicateBuilder.True<SkuInfo>();
            if (query.merchant_id > 0)
                filter = filter.And(c => c.MerchantId == query.merchant_id);
            if (!string.IsNullOrEmpty(query.name))
                filter = filter.And(c => c.Name == query.name);
            return context.SkuInfos.FromCachePaged<SkuInfo, sku_info_dto>(query.page, query.size, filter, orderBy => orderBy.OrderBy(c => c.Id));
        }

        public sku_info_dto Get(long id) {
            var query = context.SkuInfos.Where(c => c.Id == id);
            return query.FromCacheFirstOrDefault<SkuInfo, sku_info_dto>();
        }
        /// <summary>
        /// 保存规格
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ApiResultMessage Save(sku_info_model dto) {
            int result = 0;
            if (dto.id > 0)
                result = Update(dto);
            else
                result = Add(dto);
            return new ApiResultMessage("保存成功");
        }

        public long Save(sku_info_dto dto) {
            var merchant_no = context.Merchants.Where(o => o.Id == dto.merchant_id).Select(o => o.MerchantNo).FirstOrDefault();
            var model = new sku_info_model() { id = dto.id, name = dto.name, merchant_no = merchant_no,bind_no = merchant_no, sku_values = dto.sku_values };
            var result = dto.id > 0 ? Update(model) : Add(model);
            return result;
        }

        public int Add(sku_info_model dto) {
            if (dto.sku_values.Count == 0)
                throw new ServerErrorException("规格没有项目");
            var names = dto.sku_values.Select(c => c.name);

            if (names.Count() != names.Distinct().Count())
                throw new ServerErrorException("规格的项目有相同的值");

            foreach (var sku_value in dto.sku_values) sku_value.name = sku_value.name.Replace("-", "");

            var merchant = _iMerchantService.Get(dto.bind_no);
            if (context.SkuInfos.Exist(c => c.Name == dto.name && merchant.id == c.MerchantId))
                throw new ServerErrorException("不能有相同的规格");
            var model = dto.ToDtoObject<SkuInfo>();
            model.MerchantId = merchant.id;
            model.SkuValues = dto.sku_values.ToDtoList<SkuValue>();
            context.SkuInfos.Add(model);
            int result = _iUnitOfWork.Commit();
            return result;
        }

        public int Update(sku_info_model dto) {
            if (dto.sku_values.Count == 0)
                throw new ServerErrorException("规格没有项目");

            var names = dto.sku_values.Select(c => c.name);
            if (names.Count() != names.Distinct().Count())
                throw new ServerErrorException("规格的项目有相同的值");

            foreach (var sku_value in dto.sku_values) {
                sku_value.name = sku_value.name.Replace("-", "");
                sku_value.id = sku_value.id == 0 ? DtoHelper.GuidToLongID() : sku_value.id;
            }
            var merchant = _iMerchantService.Get(dto.bind_no);
            if (context.SkuInfos.Exist(c => c.Name == dto.name && c.MerchantId == merchant.id && c.Id != dto.id))
                throw new ServerErrorException("不能有相同的规格");

            var model = context.SkuInfos.FindById(dto.id);
            dto.ToDtoObject(model);

            var req_ids = dto.sku_values.Select(c => c.id);
            var data_ids = model.SkuValues.Select(c => c.Id).CopyToList();
            //新增
            req_ids.Except(data_ids).DataForEach(id => {
                var item = dto.sku_values.First(c => c.id == id);
                model.SkuValues.Add(new SkuValue { SkuId = model.Id, Name = item.name });
            });
            //删除
            data_ids.Except(req_ids).DataForEach(id => {
                var product_sku = (from child in context.ProductSkus
                                   where ("-" + child.SkuPath + "-").Contains("-" + id + "-")
                                   select child).ToList();
                if (product_sku.Count > 0)
                    throw new ServerErrorException(string.Format("不能删除，因为商品\"{0}\"在使用", product_sku.Select(c => c.Product.Name).Aggregate((x, y) => x + "," + y)));
                var item = model.SkuValues.First(c => c.Id == id);
                context.Entry(item).State = EntityState.Deleted;
            });
            //更新
            req_ids.Intersect(data_ids).DataForEach(filter_id => {
                var item = dto.sku_values.First(c => c.id == filter_id);
                var model_item = model.SkuValues.First(c => c.Id == filter_id);
                item.ToDtoObject(model_item);
                context.Entry(model_item).State = EntityState.Modified;
            });

            int result = _iUnitOfWork.Commit();
            return result;
        }

        public int Delete(long id) {
            var item = context.SkuInfos.Find(id);
            var value_ids = item.SkuValues.Select(c => c.Id);
            foreach (var value_id in value_ids) {
                var product_sku = context.ProductSkus.SqlQuery(string.Format("select * from mc_ProductSku where '-'+SkuPath+'-' like '%-{0}-%'", value_id)).ToList();
                if (product_sku.Count > 0)
                    throw new ServerErrorException(string.Format("不能删除，因为商品\"{0}\"在使用", product_sku.Select(c => c.Product.Name).Aggregate((x, y) => x + "," + y)));
            }
            context.SkuInfos.Remove(item);
            int result = _iUnitOfWork.Commit();
            return result;
        }

        public ApiResultMessage DeleteSku(long id) {
            var item = context.SkuInfos.Find(id);
            var value_ids = item.SkuValues.Select(c => c.Id);
            foreach (var value_id in value_ids) {
                var product_sku = context.ProductSkus.SqlQuery(string.Format("select * from mc_ProductSku where '-'+SkuPath+'-' like '%-{0}-%'", value_id)).ToList();
                if (product_sku.Count > 0)
                    throw new ServerErrorException(string.Format("不能删除，因为商品\"{0}\"在使用", product_sku.Select(c => c.Product.Name).Aggregate((x, y) => x + "," + y)));
            }
            context.SkuValues.RemoveRange(item.SkuValues);
            context.SkuInfos.Remove(item);
            int result = _iUnitOfWork.Commit();
            if (result > 0)
                return ApiResultToJson.Success("删除成功");
            else
                return ApiResultToJson.Fail("删除失败");
        }

        public List<sku_value_dto> Gets(sku_value_dto dto) {
            Expression<Func<SkuValue, bool>> filter = c => true;
            if (!string.IsNullOrEmpty(dto.name))
                filter = filter.And(c => c.Name == dto.name);
            return context.SkuValues.Where(filter).FromCache<SkuValue, sku_value_dto>();
        }

        public long Save(sku_value_dto dto) {
            if (string.IsNullOrEmpty(dto.name))
                throw new ServerErrorException("规格名称不能为空");
            if (dto.id > 0) {
                var model = context.SkuValues.FirstOrDefault(c => c.Id == dto.id);
                dto.ToDtoObject(model);
            } else {
                context.SkuValues.Add(dto.ToDtoObject<SkuValue>());
            }
            return _iUnitOfWork.Commit();
        }

        public long DelSkuValue(long id) {
            var model = context.SkuValues.FirstOrDefault(c => c.Id == id);
            context.SkuValues.Remove(model);
            return _iUnitOfWork.Commit();
        }
    }
}
